/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#include "StdAfx.h"
#include "Cvars.h"
#include <stdlib.h>
#include <sstream>

#include "shared/StringUtil.h"
#include "Kernel.h"


Cvars::Cvars(void)
{
    m_listCmd.Set( this );
}

/**
======================
Initialize cvars 
======================
*/
void Cvars::Init( Kernel* kernel )
{
    //
    // Video properties
    RegisterCvar("v_height", "600", 600.0f, CVAR_SAVE);
    RegisterCvar("v_width", "800", 800.0f, CVAR_SAVE);
    RegisterCvar("v_render", "opengl", 0.0f, CVAR_SAVE);
    RegisterCvar("v_fullscreen", "0", 0.0f, CVAR_SAVE);
    RegisterCvar("v_maxfps", "30", 30.0f, CVAR_SAVE);
    RegisterCvar("v_freq", "32", 32.0f, CVAR_SAVE );
    RegisterCvar("v_vsync", "0", 0.0f, CVAR_SAVE );
    RegisterCvar("v_windowtitle", "Myriad3D", 0.0f, CVAR_SAVE );
    RegisterCvar("v_debug", "0", 0.0f, CVAR_SAVE );
    RegisterCvar("v_defaultfont", "font/arial.ttf", 0.0f, CVAR_SAVE );
    RegisterCvar("v_fontalias", "1", 1.0f, CVAR_SAVE );
    
    //
    // Sound properties
    RegisterCvar("s_sound", "1", 1.0f, CVAR_SAVE);
    RegisterCvar("s_volume", "0.8", 0.8f, CVAR_SAVE);
    RegisterCvar("s_mainVolume", "0.8", 0.8f, CVAR_SAVE);

    //
    // Util properties
    RegisterCvar("d_logger", "1", 1.0f, CVAR_SAVE);
    RegisterCvar("d_keysym", "1", 1.0f, CVAR_SAVE);
    RegisterCvar("d_consoleBackgroundColor", "", 0.12f, 0.15f, 0.12f, CVAR_SAVE );
    RegisterCvar("d_consoleBackgroundColorAlpha", "", 0.48f, CVAR_SAVE );
    RegisterCvar("d_consoleForegroundColor", "", 0, 1, 0, CVAR_SAVE );
    RegisterCvar("d_fps" , "1", 1.0f, CVAR_SAVE);

    //
    // Input properties
    RegisterCvar("i_joystick", "1", 1.0f, CVAR_SAVE);
    RegisterCvar("i_input", "1", 1.0f, CVAR_SAVE );

    //
    // Game properties
    RegisterCvar("startscript", "startup.lua", 0.0f, CVAR_SAVE|CVAR_PROTECT );
    RegisterCvar("g_menu_script", "menu_init.lua", 0.0f, CVAR_SAVE|CVAR_PROTECT );

    kernel->GetConsole()->AddCommand( &m_listCmd, "cvarlist" );
}

/** Retreive a Cvar */
cvar* Cvars::GetCvar( const std::string &cvarName )
{
    std::string cVar = StringUtil::ToLower( cvarName );
    if ( cvarList.find( cVar ) != cvarList.end() )
    {
        return cvarList[ cVar ];
    }   
    return NULL;
}

/** Get a cvar float value */
float Cvars::GetFloatValue( const std::string &cvar_name )
{
    cvar* c = GetCvar( cvar_name );
    if ( c ) 
        return c->fvalue;
    else
        return 0;
}

/** Get a string value */
std::string Cvars::GetStringValue( const std::string &cvar_name )
{
    cvar* c = GetCvar( cvar_name );
    if ( c ) 
        return c->svalue;
    else
        return "";

}

/** Get a vector */
MVector3f   Cvars::GetVectorValue( const std::string &cvar_name )
{
    cvar* c = GetCvar( cvar_name );
    if ( c ) 
        return c->vector;
    else
        return MVector3f(0,0,0);
}

/** Create a cvar */
void Cvars::RegisterCvar( const std::string &cvar_name, const std::string &sval, float v1, float v2, float v3, bool boolean, int Flags )
{
    cvar* c = new cvar;
    c->flags     = Flags;
    c->fvalue    = v1;
    c->name      = StringUtil::ToLower( cvar_name );
    c->svalue    = sval;
    c->valid     = true;     // make a valid cvar
    c->vector.set( v1, v2, v3 );

    cvarList[ c->name ] = c;
}

/** Remove a cvar */
void Cvars::RemoveCvar( const std::string &cvar_name )
{
    std::string str = StringUtil::ToLower( cvar_name );
    if ( cvarList.find( str ) != cvarList.end() )
    {
        cvar* c = GetCvar( str );
        cvarList.erase( str );
        delete c;
        
    }
}

/** Set a cvar value */
bool Cvars::SetCvarValue( const std::string &name, float val )
{
    cvar* c = GetCvar( name );
    if ( c ) 
    {
        // make sure it is not write protected
        if ( c->flags & CVAR_PROTECT )
        {
            return false;
        }
        // fill in the values
        c->fvalue = val;
        // convert a float to a string
        std::stringstream buf;
        buf << val;
        c->svalue = buf.str();
        return true;
    }
    return false;
}

/** Set a cvar value */
bool Cvars::SetCvarValue(const std::string &name, const std::string &value)
{
    cvar* c = GetCvar( name );
    // check if the cvar exists
    if ( c)
    {
        // make sure it is not write protected
        if ( c->flags & CVAR_PROTECT )
        {
            return false;
        }
        // fill in the values
        c->fvalue = (float)atof(value.c_str());
        c->svalue = value;
        return true;
    }
    return false;
}

/** Set a cvar value */
bool Cvars::SetCvarValue( const std::string &name, const MVector3f &v )
{
    cvar* c = GetCvar( name );
    if ( c )
    {
        c->vector.set( v.X, v.Y, v.Z );
        return true;
    } return false;
}

/**
==========================
Check to see if this is a valid cvar
==========================
*/
bool Cvars::IsValid(const std::string &name)
{
    cvar* c = GetCvar( name );
    return ( c != NULL );
}


Cvars::~Cvars(void)
{
    type_CvarList::iterator it;
    for( it = cvarList.begin(); it!=cvarList.end(); ++it )
        delete it->second;
}


    /*---------------------------------------------------
        List Command
    ---------------------------------------------------*/



extern Kernel* g_kernel;

void Cvars::List_f::Exec(std::string &s) 
{
    type_CvarList::const_iterator it;
    int count = 0;
    /**
     * Print each cvar
     */
    for( it = g_kernel->GetCvars()->GetCvars().begin(); it != g_kernel->GetCvars()->GetCvars().end(); )
    {
        ++count;
        g_kernel->LPrintf( (it->second->name + " = " + it->second->svalue).c_str() );
        ++it;
    }
    // convert a float to a string
    std::stringstream buf;
    buf << count;
    g_kernel->LPrintf( ("  Total cvars: " + buf.str()).c_str() );
}